#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "symbol.h"
#include "lex.h"
extern DynArray tktable; // 单词表;
extern int token;
Type char_pointer_type;                  // 字符串指针
Type int_type;                           // int 类型
Type default_func_type;                  // 缺省函数类型
Stack global_sym_stack, local_sym_stack; // 全局符号栈和局部符号栈
/*
功能:初始化栈存储容量
stack:栈存储结构
initsize:栈初始化分配空间
*/
void stack_init(Stack *stack, int initsize)
{
    stack->base = (void **)malloc(sizeof(void **) * initsize);
    if (!stack->base)
    {
        errorMsg("内存分配失败");
    }
    else
    {
        stack->top = stack->base;
        stack->stacksize = initsize;
    }
}
/*
stack:栈存储结构
element:要插入栈顶的新元素
size:栈元素的实际数据尺寸
返回值:栈顶元素
*/
void *stack_push(Stack *stack, void *element, int size)
{
    int newsize;
    if (stack->top >= stack->base + stack->stacksize)
    {
        newsize = stack->stacksize * 2;
        stack->base = (void **)realloc(stack->base, sizeof(void **) * newsize);
        if (!stack->base)
        {
            return NULL;
        }
        stack->top = stack->base + stack->stacksize;
        stack->stacksize = newsize;
    }
    *stack->top = (void **)malloc(size);
    memcpy(*stack->top, element, size);
    stack->top++;
    return *(stack->top - 1);
}

/*
功能:弹出栈顶元素
stack：栈存储结构
*/
void stack_pop(Stack *stack)
{
    if (stack->top > stack->base)
    {
        free(*(--stack->top));
    }
}

/*
功能:得到栈顶元素
stack:栈存储结构
返回值:栈顶元素
*/
void *stack_get_top(Stack *stack)
{
    void **element;
    if (stack->top > stack->base)
    {
        element = stack->top - 1;
        return *element;
    }
    else
    {
        return NULL;
    }
}

/*
功能:判断栈是否为空
stack:栈存储结构
返回值:1表示栈为空，0表示栈非空
*/
int stack_is_empty(Stack *stack)
{
    if (stack->top == stack->base)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void stack_destroy(Stack *stack)
{
    void **element;
    for (element = stack->base; element < stack->top; element++)
    {
        free(*element);
    }
    if (stack->base)
    {
        free(stack->base);
    }
    stack->base = NULL;
    stack->top = NULL;
    stack->stacksize = 0;
}

/*
功能:将符号放在符号栈中
v:符号编号
type:符号数据类型
c:符号关联值
*/
Symbol *sym_direct_push(Stack *ss, int v, Type *type, int c)
{
    Symbol s, *p;
    s.v = v;
    s.type.t = type->t;
    s.type.ref = type->ref;
    s.c = c;
    s.next = NULL;
    p = (Symbol *)stack_push(ss, &s, sizeof(Symbol));
    return p;
}

/*
功能:将符号放在符号栈中，动态判断是放在全局符号栈还是局部符号栈
v:符号编号
type:符号数据类型
r:符号存储类型
c:符号关联值
*/
Symbol *sym_push(int v, Type *type, int r, int c)
{
    Symbol *ps, **pps;
    TkWord *ts;
    Stack *ss;
    if (stack_is_empty(&local_sym_stack) == 0)
    {
        ss = &local_sym_stack;
    }
    else
    {
        ss = &global_sym_stack;
    }
    ps = sym_direct_push(ss, v, type, c);
    ps->r = r;
    // 不记录结构体成员及匿名符号
    if ((v & SC_STRUCT) || v < SC_ANOM)
    {
        // 更新单词sym_struct或 sym_identifier字段
        ts = (TkWord *)tktable.data[(v & ~SC_STRUCT)];
        if (v & SC_STRUCT)
        {
            pps = &ts->sym_struct;
        }
        else
        {
            pps = &ts->sym_identifier;
        }
        ps->prev_tok = *pps;
        *pps = ps; //????
    }
    return ps;
}

/*
功能:将函数符号放入全局符号表中
v:符号编号
type:符号数据类型
*/
Symbol *func_sym_push(int v, Type *type)
{
    Symbol *s, **ps;
    s = sym_direct_push(&global_sym_stack, v, type, 0);
    ps = &((TkWord *)tktable.data[v])->sym_identifier;
    // 同名符号，函数符号放在最后 ->->...s
    while (*ps != NULL)
    {
        ps = &(*ps)->prev_tok;
    }
    s->prev_tok = NULL;
    *ps = s;
    return s;
}

/*
功能:查找结构体定义
v:符号编号
*/
Symbol *struct_search(int v)
{
    if (v >= tktable.count)
    {
        return NULL;
    }
    else
    {
        return ((TkWord *)tktable.data[v])->sym_struct;
    }
}

/*
功能:查找结构定义
v:符号编号
*/
Symbol *sym_search(int v)
{
    if (v >= tktable.count)
    {
        return NULL;
    }
    else
    {
        return ((TkWord *)tktable.data[v])->sym_identifier;
    }
}

/*
功能:变量的符号放入栈中

*/
Symbol *var_sym_put(Type *type, int r, int v, int addr)
{
    Symbol *sym = NULL;
    if ((r & SC_VALMASK) == SC_LOCAL)
    { // 局部变量
        sym = sym_push(v, type, r, addr);
    }
    else if (v && (r & SC_VALMASK) == SC_GLOBAL) // 全局变量
    {
        sym = sym_search(v);
        if (sym)
        {
            errorMsg("%s重定义\n", ((TkWord *)tktable.data[v])->spelling);
        }
        else
        {
            sym = sym_push(v, type, r | SC_SYM, 0);
        }
    }
    // else 字符串常量符号
    return sym;
}

/*
功能:将节名称放入全局符号表
sec:节名称
c:符号关联值
*/

/*
功能:将节名称放入全局符号表
sec:节名称
c:符号关联值
*/
Symbol *sec_sym_put(char *sec, int c)
{
    TkWord *tp;
    Symbol *s;
    Type type;
    type.t = T_INT;
    tp = tkword_insert(sec);
    token = tp->tkcode;
    s = sym_push(token, &type, SC_GLOBAL, c);
    return s;
}

/*
功能:弹出栈中符号知道栈顶符号为b
ptop:符号栈栈顶
b:符号指针
*/
void sym_pop(Stack *ptop, Symbol *b)
{
    Symbol *s, **ps;
    TkWord *ts;
    int v;
    s = (Symbol *)stack_get_top(ptop);
    while (s != b)
    {
        v = s->v;
        // 更新单词表中sym_struct sym_identifier
        if ((v & SC_STRUCT) || v < SC_ANOM)
        {
            ts = (TkWord *)tktable.data[(v & ~SC_STRUCT)];
            if (v & SC_STRUCT)
            {
                ps = &ts->sym_struct;
            }
            else
            {
                ps = &ts->sym_identifier;
            }
            *ps = s->prev_tok;
        }
        stack_pop(ptop);
        s = (Symbol *)stack_get_top(ptop);
    }
}
